package com.manager.common.ssh;

import com.jcraft.jsch.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

@SuppressWarnings("all")
public class RemoteExecuteLinuxCommandTools {

	/****
	 *
	 * 只支持linux
	 *
	 ***/
	public static boolean uploadFileBySFTP(String ip, String userName, String password, int port,
										   String remoteDirPath, String remoteFilName, String localFilePath,List<String> out)  {

		JSch jsch = new JSch();
		Session sshSession = null;
		Channel channel = null;
		ChannelSftp sftp = null;

		try{

			sshSession = jsch.getSession(userName, ip, port);

			if (!StringUtils.isEmpty(password)) {
				sshSession.setPassword(password);
			}

			Properties sshConfig = new Properties();
			sshConfig.put("StrictHostKeyChecking", "no");

			sshSession.setConfig(sshConfig);

			sshSession.connect();

			channel = sshSession.openChannel("sftp");
			channel.connect();

			sftp = (ChannelSftp) channel;

			mkdir(remoteDirPath, sftp);

			sftp.put(localFilePath, remoteDirPath + "/" + remoteFilName);

			return true;

		}catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			out.add(e.getMessage());
		}finally {

			if(channel != null){
				channel.disconnect();
			}
			if(sshSession != null){
				sshSession.disconnect();
			}
			if(sftp != null){
				sftp.disconnect();
			}

		}

		return false;

	}


	private static void mkdir(String remoteDirPath,ChannelSftp sftp) throws SftpException{
		String[] arr = remoteDirPath.split("/");
		String temp = "/";
		for(String path:arr){
			if(StringUtils.isEmpty(path)){
				continue;
			}
			temp += path + "/";
			try {
				sftp.lstat(temp).isDir();
			} catch (Exception e) {
				// TODO: handle exception
				sftp.mkdir(temp);
				sftp.cd(temp);
			}
		}
	}


	/***
	 *
	 * 远程批量执行linux命令
	 *
	 **/
	public static boolean excuteRemoteSSH(String ip, String userName, String password, int port,
										  List<String> out,String... commands) {

		JSch jsch = new JSch();
		Session session = null;
		boolean hasSuccess = false;
		try{
			session = jsch.getSession(userName, ip, port);
			session.setPassword(password);

			Properties sshConfig = new Properties();
			sshConfig.put("StrictHostKeyChecking", "no");

			session.setConfig(sshConfig);

			session.connect(60 * 1000);

			String buffer;
			InputStreamReader isr = null;
			BufferedReader reader = null;

			for (String command : commands) {
				boolean flag = true;
				Channel channel = session.openChannel("exec");
				ChannelExec channelExec = (ChannelExec) channel;


				channel.setInputStream(null);
			//	channelExec.setErrStream(System.err);

				InputStream errorIn = channelExec.getErrStream();
				InputStream successIn = channelExec.getInputStream();

				channelExec.setCommand(command);
				channel.connect();

				isr = new InputStreamReader(errorIn, StandardCharsets.UTF_8);
				reader = new BufferedReader(isr);

				while ((buffer = reader.readLine()) != null) {
					hasSuccess = false;
					flag = false;
					out.add(buffer);
				}

				isr = new InputStreamReader(successIn, StandardCharsets.UTF_8);
				reader = new BufferedReader(isr);

				while ((buffer = reader.readLine()) != null) {
					hasSuccess = true;
					out.add(buffer);
				}

				isr.close();
				reader.close();

				channelExec.disconnect();

				channel.disconnect();

				if(!flag){
					break;
				}
			}

			return out.size() == 0 ? true : hasSuccess;

		}catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			out.add(e.getMessage());
			hasSuccess = false;
		}finally {
			if(session != null){
				session.disconnect();
			}
		}

		return hasSuccess;
	}

	public static boolean excuteRemoteSSH(Session session,
										  List<String> out,String... commands) {


		try{
			String buffer;
			InputStreamReader isr = null;
			BufferedReader reader = null;

			for (String command : commands) {

				out.add(command);
				Channel channel = session.openChannel("exec");
				ChannelExec channelExec = (ChannelExec) channel;

				channelExec.setCommand(command);
				channel.setInputStream(null);
				channelExec.setErrStream(System.err);
				channel.connect();

				InputStream in = channelExec.getInputStream();
				isr = new InputStreamReader(in, StandardCharsets.UTF_8);
				reader = new BufferedReader(isr);

				while ((buffer = reader.readLine()) != null) {
					out.add(buffer);
				}

				isr.close();
				reader.close();

				channelExec.disconnect();

				channel.disconnect();

			}

			return true;

		}catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			out.add(e.getMessage());
		}finally {
		}

		return false;
	}

	/**
	 * 验证ip是否可联通
	 * @param ip
	 * @return
	 */
	public static boolean isPingWorkInfo(String ip){
		boolean iscollect = false;
		String cmdPing = "ping "+ip;
		Runtime run = Runtime.getRuntime();
		Process process;
		try {
			process = run.exec(cmdPing);
			process.waitFor();
			BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream(), Charset.forName("GBK")));
			String line = null;
			while ((line = br.readLine()) != null){
				if(line.contains("无法访问目标主机")||line.contains("请求超时")){
					iscollect = false;
					break;
				}else if(line.contains("统计信息")||line.contains("字节=")){
					iscollect = true;
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return iscollect;
	}
	/**
	 * 验证端口是否可用
	 * @param ip
	 * @param port
	 * @return
	 */
	public static boolean isUsePort(String ip,Integer port){
		boolean isUse = false;
		String cmdStr = "nc -nvv -w2 "+ip+" "+port;
		Runtime run = Runtime.getRuntime();
		Process process;
		try {
			process = run.exec(cmdStr);
			process.waitFor();
			BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream(), Charset.forName("GBK")));
			String line = null;
			while ((line = br.readLine()) != null){
				if(line.contains("CONNECT SUCCESS")){ //说明该端口已被其他程序占用，无法使用
					break;
				}else if(line.contains("CONNECT ERROR")){
					isUse = true;
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return isUse;
	}


	public static void main(String[] args) throws JSchException, SftpException, IOException {
//		String host = "192.168.1.3";   //"192.168.3.149";
//		String userName = "root";
//		String password = "root";     //"Lh2011062064";
//
//		List<String> out = new ArrayList<String>();
//		List<String> commandList = new ArrayList<>();
//
//		commandList.add("/data/t.sh");
//
//		RemoteExecuteLinuxCommandTools.excuteRemoteSSH(host, userName, password, 22, out,commandList.toArray(new String[]{}));
//
//		for (String result : out) {
//			System.out.println(result);
//		}

//		boolean isActive =  isActive(host, userName, password, 22, "node_exporter.service",out);
//
//		System.out.println(isActive);

		System.out.println("=============结束==============");
		
		
		/*RemoteExecuteLinuxCommandTools.uploadInstallFileBySFTP(host, userName,password,

				22, basePath+"/node_exporter", "upload.sh"," E:\\upload\\fda2b480d30a44f9939a6ff7c784b6b6.sh");*/
//		List<String> commandList = new ArrayList<>();
//		//commandList.add("su");
//		//commandList.add("123456");
//		//commandList.add("nestat -nlp|grep :9100");ps aux | grep elasticsearch,grafana-zg,node_exporter,
//		String command = " ./getProcessesInfo.sh grafana-zg,node_exporter,docker,elasticsearch,";
//		//./getProcessesInfo.sh node_exporter
//		RemoteExecuteLinuxCommandTools.excuteRemoteSSH(host, userName, password, 22, command, out);
//		List<MainFrameService> services = new ArrayList<MainFrameService>();
//		for(int i=0;i<out.size();i++){
//			if(out.get(i).contains("servive-name：") && !out.get(i+1).contains("servive-name：")){
//				MainFrameService service = new MainFrameService();
//				service.setServiceName(out.get(i).split("：")[1]);
//				service.setCpuVal(out.get(i+1));
//				service.setMemoryVal(out.get(i+2));
//				service.setAlias(out.get(i+3));
//				services.add(service);
//			}
//		}
//		 System.out.println(services.toArray());
//
//		  String osName = System.getProperties().getProperty("os.name");
//		  System.out.println("当前操作系统为"+osName);
		
		/*String dockerVersion = "";
		for (String result : out) {
			if(result.contains("Version:")){
				String[] strs1 = result.split(" ");
				dockerVersion = strs1[strs1.length-1];
				break;
			}
		}
		System.out.println("当前docker版本为:"+dockerVersion);
		out = new ArrayList<String>();
		String commandDockerStats = "docker stats --no-stream";
		RemoteExecuteLinuxCommandTools.excuteRemoteSSH(host, userName, password, 22, commandDockerStats, out);
		Map<String,String> map2 = new HashMap<String,String>();
		for(int j=1;j<out.size();j++){
			String result = out.get(j);
			String[] res = result.split(" ");
			String[] notEmptyRes = deleteArrayNull(res);
			if(notEmptyRes!=null && notEmptyRes.length>0){
				if(dockerVersion.contains("1.13")){ 
					map2.put(notEmptyRes[0],notEmptyRes[1]+","+notEmptyRes[7]);
					}
				if(dockerVersion.contains("19.03")){ 
					map2.put(notEmptyRes[1],notEmptyRes[2]+","+notEmptyRes[6]);
					}
			}
		}
		Map<String,String> resultMap = new HashMap<String,String>();
		if(dockerVersion.contains("1.13")){
			//获取对应的容器ID和容器名字
			out = new ArrayList<String>();
			String commandDockerPs = "docker ps"; //./getProcessesInfo.sh node_exporter
			RemoteExecuteLinuxCommandTools.excuteRemoteSSH(host, userName, password, 22, commandDockerPs, out);
			Map<String,String> map = new HashMap<String,String>();
			for(int j=1;j<out.size();j++){
				String result = out.get(j);
				String[] res = result.split(" ");
				String[] notEmptyRes = deleteArrayNull(res);
				if(notEmptyRes!=null && notEmptyRes.length>0){
						map.put(notEmptyRes[0], notEmptyRes[1]);
				}
			}
	        Iterator<Map.Entry<String,String>> it = map.entrySet().iterator();
	        while (it.hasNext()) {
	            Map.Entry<String,String> entry = it.next();
	            resultMap.put(entry.getValue(), map2.get(entry.getKey()));
	        }
		}else{
			resultMap = map2;
		}
		System.out.println("最终结果："+resultMap.toString());*/
	}
	public static String[] deleteArrayNull(String[] string) {
		String[] array = string;
		// 声明一个list
		List<String> list= new ArrayList<>(string.length);
		for (String str : array) {
			list.add(str.trim());
		}
		// 删除空的值
		while (list.remove(null));
		while (list.remove(""));
		// 将list 转换成数组
		String[] list2 = list.toArray(new String[list.size()]);
		// 返回删除空值后的数组
		return list2;
	}

}
